/*
 * Phase.h
 *
 *  Created on: 23 May 2011
 *      Author: allan
 */

#ifndef PHASE_H_
#define PHASE_H_

// C++ includes
#include <memory>
#include <string>
#include <vector>
using namespace std;

// Eigen includes
#include <Eigen/Core>
using namespace Eigen;

// GeoReact includes
#include "Activity.h"

class Phase
{
public:
	Phase();
	
	Phase(const string& name);
	
	Phase(const string& name, const vector<string>& species);
	
	template<class ActivityType> 
	Phase(const string& name, const vector<string>& species, const ActivityType& activity);
	
	void SetName(const string& name);
	
	void SetSpecies(const vector<string>& species);
	
	template<class ActivityType> 
	void SetActivity(const ActivityType& activity);
	
	template<class EquationOfStateType> 
	void SetEquationOfState(const EquationOfStateType& eos) {}
	
	const string GetName() const;
	
	const vector<string>& GetSpecies() const;
	
	const Activity& GetActivity() const;
	
	Activity& GetActivity();
	
	const VectorXd MolarFractions(const VectorXd& n) const;
	
	const VectorXd ActivityCoefficients(double T, double P, const VectorXd& n) const;
	
	const VectorXd Activities(double T, double P, const VectorXd& n) const;
	
private:
	/// The name of the phase
	string name;
	
	/// The species that compose the phase
	vector<string> species;
	
	/// The activity instance responsible for the calculation of the activity coefficients and activities of the species
	std::shared_ptr<Activity> activity;
};

template<class ActivityType> Phase::Phase(const string& name, const vector<string>& species, const ActivityType& activity) :
name(name), species(species) { SetActivity(activity); }

template<class ActivityType> void Phase::SetActivity(const ActivityType& activity)
{ this->activity = std::shared_ptr<Activity>(new ActivityType(activity)); }

inline const string Phase::GetName() const 
{ return name; }

inline const vector<string>& Phase::GetSpecies() const 
{ return species; }

inline const Activity& Phase::GetActivity() const
{ return *activity; }
	
inline Activity& Phase::GetActivity()
{ return *activity; }

inline const VectorXd Phase::MolarFractions(const VectorXd& n) const 
{ return n / n.sum(); }

inline const VectorXd Phase::ActivityCoefficients(double T, double P, const VectorXd& n) const
{ return activity->ActivityCoefficients(T, P, n); }

inline const VectorXd Phase::Activities(double T, double P, const VectorXd& n) const
{ return activity->Activities(T, P, n); }


#endif /* PHASE_H_ */
